using System;
using System.Diagnostics;

namespace OR.Reuse.Reflection
{
	/// <summary>
	/// A utility class used for managing class properties.
	/// </summary>
	public class PropertyHandler
	{
	
		/// <summary>
		/// The error message to display when an rvalue is invalid.
		/// </summary>
		private const string ERROR_INVALID_RVALUE = "The rvalue is invalid.";

		/// <summary>
		/// The error message to display when an rvalue is null.
		/// </summary>
		private const string ERROR_NULL_RVALUE = "The rvalue is null.";

		/// <summary>
		/// The error message to display when an rvalue is outside the defined range of values.
		/// </summary>
		private const string ERROR_INVALID_RANGE = "The rvalue is out of range.";

		/// <summary>
		/// The error message to display when an rvalue is empty.
		/// </summary>
		private const string ERROR_EMPTY_RVALUE = "The rvalue cannot be an empty string or only whitespace.";

		/// <summary>
		/// The class constructor.  This does nothing as this class is a utility class.
		/// </summary>
		public PropertyHandler()
		{
		}

		/// <summary>
		/// Assigns a string to a referenced string property.
		/// </summary>
		/// <param name="pProperty">The property that should have an assigned value.</param>
		/// <param name="pValue">The value to be assigned to a property.</param>
		[ ObsoleteAttribute( "This method is depreciated.  Use string CheckString( string ) instead.", true ) ]
		public static void SetStringProperty( ref string pProperty, string pValue )
		{
			Debug.Assert( ( null != pValue) && 
				( string.Empty != pValue ) && 
				( 0 < pValue.Trim( ).Length ), "The rvalue is invalid." );
			
			if ( null == pValue) 
			{
				throw new ArgumentNullException( PropertyHandler.ERROR_INVALID_RVALUE );
			}
			if ( ( string.Empty == pValue ) || ( 0 == pValue.Trim( ).Length ) ) 
			{
				throw new ArgumentOutOfRangeException( "The rvalue cannot be an empty string or only whitespace." );
			}
			pProperty = pValue.Trim( );

			//Debug.Assert( pProperty.Equals( pValue ), "The assigned property and original value are inconsistent." );
		}

		/// <summary>
		/// Determines whether or not a string contains any value.
		/// </summary>
		/// <param name="pValue">The string value to check.</param>
		/// <returns>The string value.</returns>
		public static string CheckString( string pValue )
		{
			Debug.Assert( ( null != pValue) && 
				( string.Empty != pValue ) && 
				( 0 < pValue.Trim( ).Length ), "The rvalue is invalid." );
			
			if ( null == pValue) 
			{
				throw new ArgumentNullException( PropertyHandler.ERROR_INVALID_RVALUE );
			}
			if ( ( string.Empty == pValue ) || ( 0 == pValue.Trim( ).Length ) ) 
			{
				throw new ArgumentOutOfRangeException( PropertyHandler.ERROR_EMPTY_RVALUE );
			}
			return pValue.Trim( );
		}

		/// <summary>
		/// Assigns an object to a referenced object property.
		/// </summary>
		/// <param name="pProperty">The property that should have an assigned object.</param>
		/// <param name="pValue">The object to be assigned to a property.</param>
		public static object CheckObject( object pValue )
		{
			Debug.Assert( null != pValue, "The rvalue is invalid." );
			
			if ( null == pValue )
			{
				throw new System.ArgumentNullException( PropertyHandler.ERROR_NULL_RVALUE );
			}
			return pValue;
		
		}

		/// <summary>
		/// Ensures a value is a positive value such that 0 < X.
		/// </summary>
		/// <param name="pValue">The value to check.</param>
		/// <returns>The value if the value satisfies the condition, and exception otherwise.</returns>
		public static int CheckPositive( int pValue )
		{
			Debug.Assert( 0 < pValue, "The value is not positive." );
			if ( 1 > pValue && ( ! pValue.Equals( int.MinValue ) ) )
			{
				throw new System.ArgumentOutOfRangeException( PropertyHandler.ERROR_INVALID_RANGE );
			}
			return pValue;
		}

		/// <summary>
		/// Ensures a value is a positive value such that 0 < X.
		/// </summary>
		/// <param name="pValue">The value to check.</param>
		/// <returns>The value if the value satisfies the condition, and exception otherwise.</returns>
		public static long CheckPositive( long pValue )
		{
			Debug.Assert( 0 < pValue, "The value is not positive." );
			if ( 1 > pValue && ( ! pValue.Equals( long.MinValue ) ) )
			{
				throw new System.ArgumentOutOfRangeException( PropertyHandler.ERROR_INVALID_RANGE );
			}
			return pValue;
		}

		/// <summary>
		/// Ensures a value is a positive value such that 0 < X.
		/// </summary>
		/// <param name="pValue">The value to check.</param>
		/// <returns>The value if the value satisfies the condition, and exception otherwise.</returns>
		public static float CheckPositive( float pValue )
		{
			Debug.Assert( 0 < pValue, "The value is not positive." );
			if ( 1.0 > pValue && ( ! pValue.Equals( float.MinValue ) ) )
			{
				throw new System.ArgumentOutOfRangeException( PropertyHandler.ERROR_INVALID_RANGE );
			}
			return pValue;
		}

		/// <summary>
		/// Ensures a value is a non-negative value such that -1 < X.
		/// </summary>
		/// <param name="pValue">The value to check.</param>
		/// <returns>The value if the value satisfies the condition, and exception otherwise.</returns>
		public static int CheckNonNegative( int pValue )
		{
			Debug.Assert( -1 < pValue, "The value is not positive." );
			if ( 0 > pValue && ( ! pValue.Equals( int.MinValue ) ) )
			{
				throw new System.ArgumentOutOfRangeException( PropertyHandler.ERROR_INVALID_RANGE );
			}
			return pValue;
		}

		/// <summary>
		/// Ensures a value is a non-negative value such that -1 < X.
		/// </summary>
		/// <param name="pValue">The value to check.</param>
		/// <returns>The value if the value satisfies the condition, and exception otherwise.</returns>
		public static long CheckNonNegative( long pValue )
		{
			Debug.Assert( -1 < pValue, "The value is not positive." );
			if ( 0 > pValue && ( ! pValue.Equals( long.MinValue ) ) )
			{
				throw new System.ArgumentOutOfRangeException( PropertyHandler.ERROR_INVALID_RANGE );
			}
			return pValue;
		}

		/// <summary>
		/// Ensures a value is a non-negative value such that -1 < X.
		/// </summary>
		/// <param name="pValue">The value to check.</param>
		/// <returns>The value if the value satisfies the condition, and exception otherwise.</returns>
		public static float CheckNonNegative( float pValue )
		{
			Debug.Assert( -1 < pValue, "The value is not positive." );
			if ( 0 > pValue && ( ! pValue.Equals( float.MinValue ) ) )
			{
				throw new System.ArgumentOutOfRangeException( PropertyHandler.ERROR_INVALID_RANGE );
			}
			return pValue;
		}

		/// <summary>
		/// Converts a string boolean value to a boolean type.
		/// </summary>
		/// <param name="pAppSetting">The string value representing a boolean.</param>
		/// <param name="pDefaultValue">The default value.</param>
		/// <returns>The default value if the string value is invalid or the boolean of the string value.</returns>
		public static bool GetValue( string pAppSetting, bool pDefaultValue )
		{
			bool result = pDefaultValue;

			if ( null != pAppSetting )
			{
				try
				{
					if ( String.Empty != pAppSetting.Trim( ) )
					{
							result = Boolean.Parse( pAppSetting );
					}
				} 
				catch
				{
					result = pDefaultValue;
				}
			}

			return result;
		}

		/// <summary>
		/// Converts a string boolean value to an int type.
		/// </summary>
		/// <param name="pAppSetting">The string value representing a int.</param>
		/// <param name="pDefaultValue">The default value.</param>
		/// <returns>The default value if the string value is invalid or the int of the string value.</returns>
		public static int GetValue( string pAppSetting, int pDefaultValue )
		{
			int result = pDefaultValue;
			if ( null != pAppSetting )
			{
				try
				{
					if ( String.Empty != pAppSetting.Trim( ) )
					{
						result = int.Parse( pAppSetting );
					}
				}
				catch
				{
					result = pDefaultValue;
				}

			}
			return result;

		}

	
		/// <summary>
		/// Converts a string value to an Enum type.
		/// </summary>
		/// <param name="pAppSetting">The string value representing a int.</param>
		/// <returns>The default value if the string value is invalid or the int of the string value.</returns>
		public static Enum GetValue( string pAppSetting, Enum pDefaultValue )
		{
			Enum result = pDefaultValue;
			if ( null != pAppSetting )
			{
				try
				{
					if ( String.Empty != pAppSetting.Trim( ) )
					{
						Type vEnumType = ( Type ) PropertyHandler.CheckObject( pDefaultValue.GetType( ) );
						result = ( Enum ) Enum.Parse( vEnumType, pAppSetting, true );
					}
				}
				catch
				{
					result = pDefaultValue;
				}

			}
			return result;

		}

      /// <summary>
      /// Ensures a value is provided.
      /// </summary>
      /// <param name="pAppSetting">The candidate string value.</param>
      /// <returns>The default value if the string value is invalid.</returns>
      public static string GetValue( string pAppSetting, string pDefaultValue )
      {
         string result = pDefaultValue;
         if ( null != pAppSetting )
         {
            try
            {
               if ( String.Empty != pAppSetting.Trim( ) )
               {
                  result = pAppSetting.Trim( );
               }
            }
            catch
            {
               result = pDefaultValue;
            }
         }
         return result;
      }
	
	}
}
